package org.dlsu.mt.parser;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.dlsu.mt.parser.generator.ParseTable;

/**
 * The <code>Word</code> class is the basic unit used in the parser.
 * It a data container that is shared among the Lexicon, Parser,
 * Lexical Analyzer and the Morphological Analyzer. The interpret() method is implemented as
 * returning the F-Structure of the current Word.
 *
 * @see Symbol
 */

public class Word implements Symbol{

	
	public static Vector vPOS = new Vector();
	public static boolean bStart = true;
	public static int nCount = 0;
	
	/**
	 * The string that represents the root word of the word. This is
	 * set using a morphological analyzer. By default, it is the same
	 * as the whole word.
	 */
	protected String wholeWord;

	/**
	 * The string that represents the actual word as seen in the sentence.
	 */
	protected String root;

	/**
	 * The string that indicates the current and actual POS Tag
	 * associated with the word.
	 */
	protected String actualPOSTag=null; // points to actual POS tag of word as derived

	/**
	 * The hashtable table that contains the possible POS Tags and their
	 * matching FStructures. Each key maps to a vector of FStructures that
	 * represent the possible FStrcutures for a POS Tag. The key used is
	 * the POS Tag in the form of a string.
	 */
	protected Hashtable posTags;
	
	
	protected FStructureElement fse;
	
    /**
     * Constructs a word with an empty list of possible POS Tags.
     *
     * @param   word   the actual word to be represented
     */
	public Word(String word){
		root = word;
		wholeWord = word;
		posTags = new Hashtable();

		//remove line below testong purpose only

		//if (word.equals("id"))
		//{
		//	//actualPOSTag = "POSTag1";
		//	posTags.put("POSTag1", new Vector());
		//	posTags.put("POSTag2", new Vector());
	 	//}
	 	//else
	 	//{
		//	posTags.put(word, new Vector());
		//}

	}


    /**
     * Constructs a word with the possible POS Tags
     * specified in the hashtable.
     *
     * @param   word   the actual word to be represented
     * @param   posTags   a hashtable containing the possible POS
     *                    Tags and thier matching FStructures
     */

	public Word(String word, Hashtable posTags){
		root = word;
		wholeWord = word;
		this.posTags = posTags;
	}


	/**
	 * Adds a possible POS Tag for a word and its corresponding attributes
	 * in the form of an FStructureInterface. If the POS Tag added is already
	 * a possible tag then the attribute in the form of an FStructureInterface
	 * will be added to list of possible attributes for that specific POS Tag.
	 *
	 * @param posTag the POS Tag of the entry to be added to the hashtable
	 * @param value the FStrucutre associated with the POS Tag
	 *
	 * @see FStructureInterface
	 * @see FStructure
	 * @see FStructureElement
	 */

	public void addPOSTagEntry(String posTag,FStructureInterface value)
	{
		Vector fStructures;

		if ( !posTags.containsKey(posTag))
		{
			fStructures = new Vector();
			fStructures.addElement(value);
			posTags.put(posTag, fStructures);
		}
		else
		{
			fStructures = (Vector)posTags.get(posTag);
			fStructures.addElement(value);
		}

	}

	/**
	 * Removes the POS Tag entry for the word. This removes all the possible
	 * attributes associated with the POS Tag.
	 *
	 * @param posTag the POS Tag to be removed from the hashtable
	 */

	public void removePOSTagEntry(String posTag)
	{
		posTags.remove(posTag);
	}


	/**
	 * Clears the list of POS Tag entries for the Word.
	 */

	public void clearPOSTags()
	{
		actualPOSTag = null;
		posTags.clear();
	}


	/**
	 * Returns the root word of this Word.
	 *
	 * @return the root word
	 */

	public String getRootWord(){
		return root;
	}

	/**
	 * Returns the word in the original form it was input.
	 *
	 * @return original word
	 */

	public String getWholeWord(){
		return wholeWord;
	}

	/**
	 * Returns the a clone or a copy of the word. All the objects
	 * in the used in the Word are cloned and not merely referenced.
	 *
	 * @return the clone of this object
	 */
	public Object clone()
	{
		String key;
		Enumeration e = posTags.keys();

		Hashtable clonedPOSTags = new Hashtable();
		Vector FStructures, FStructuresCopy;
		int i=0;

		while ( e.hasMoreElements())
		{

			key = (String) e.nextElement();

			FStructures = (Vector) posTags.get(key);
			FStructuresCopy = new Vector();

			for ( i=0; i< FStructures.size(); i++)
				if(FStructures.elementAt(i)!=null)
					FStructuresCopy.addElement(	((FStructureInterface)FStructures.elementAt(i)).clone());

			clonedPOSTags.put (key,FStructuresCopy);
		}

		Word w =new Word(this.getWholeWord(), clonedPOSTags);
		w.setPOSTag(actualPOSTag);

		return w;
	}


	/**
	 * Returns the XML representation of the word. This method
	 * will be used recursively by other displayXML() methods.
	 *
	 * The XML representation is as follows:
	 * <PRE>
	 *	<WORD wholeword="<the whole word>" pos="<pos tag of the word>"/>
	 * </PRE>
	 * @return the string showing the XML representation of the word
	 */
	 
	public String displayXML()
	{
		//System.out.println("haha : " + getCurrentPOSTag());
		if(Word.bStart == true)
		{
			vPOS.add(getCurrentPOSTag());
			nCount++;
			//System.out.println("IF : " + vPOS);
		}
		/*
		else
		{
			bStart = true;
			vPOS = new Vector();
			nCount = 0;
			System.out.println("ELSE");
		}*/
		return "<WORD wholeword=\""+wholeWord+"\" pos=\""+getCurrentPOSTag()+"\"/>";
	}

	/**
	 * Returns the current POS Tag that is set on the word.
	 *
	 * @return the current POS Tag that is set on the word.
 	 */

	public String getCurrentPOSTag()
	{
		return actualPOSTag;
	}

	/**
	 * Returns an Enumeration of possible POS Tags of the word.
	 *
	 * @return an Enumeration of possible POS Tags of the word.
	 */
	public Enumeration getPOSTags()
	{
		return posTags.keys();
	}

	/**
	 * Returns the number of possible POS Tags of the word.
	 *
	 * @return the number of possible POS Tags of the word.
	 */

	public int getNumberOfPOSTags()
	{
		return posTags.size();
	}

	/**
	 * Returns the Vector of possible Fstructures of the given POS Tag.
	 *
	 * @param inputTag the POS Tag to be used as a key to retrieve the FStructures
	 * @return a vector of possible Fstructures of the given POS Tag
	 * @throws NullPointerException if the given inputTag is null
	 */

	public Vector getFStructures(String inputTag) throws Exception
	{
		return (Vector) posTags.get(inputTag);
	}
	
	/**
	 * Sets the current POS Tag of the word.
	 *
	 * @param newTag the POS Tag of the word
	 */

	public void setPOSTag(String newTag)
	{
		actualPOSTag = newTag;
		
	}

	/**
	 * Sets the current POS Tag of the word.
	 *
	 * @param root the root word to be assigned
	 */
	public void setRootWord(String root){
		this.root = root;
	}
	
	/**
	 * Returns the interpretation of the Word object which can be overwritten
	 * to have a different output. But the current implementation is it returns
	 * an FStructure.This only returns the first one and the interpret method does not exhaust
	 * all the possible semantic structures from the word.
	 *
	 * @return The FStructure of the word
	 */
	public Object interpret() throws Exception{
		
		if (wholeWord.equalsIgnoreCase(ParseTable.ENDMARKER) || wholeWord.equalsIgnoreCase(ParseTable.EMPTY))
			return null;
		if (actualPOSTag != null)
			return ( (FStructureInterface) ((Vector) posTags.get(actualPOSTag)).elementAt(0)).clone();
		return null;
	}
	
}